#include <GL/glew.h>
#include <SDL/SDL.h>
#include <math.h>

#include "BuilderController.h"

using namespace std;

BuilderController::BuilderController(Object *player, SimpleWorld *world, vector<Mesh*> buildingMeshes) {
	moveForward = SDLK_w;
	moveBackward = SDLK_s;
	strafeLeft = SDLK_a;
	strafeRight = SDLK_d;

	this->player = player;
	this->building = world->newObject(buildingMeshes[0]);
	this->world = world;
	this->buildingMeshes = buildingMeshes;
	buildingIndex = 0;

	BuilderMotionController *bmc = new BuilderMotionController(player);
	motionController = bmc;
	bmc->setMaxVelocity(20);

	rotating = false;

	ground.n = Vector3(0, 1, 0);
	ground.p = Vector3(0, 0, 0);
}

void BuilderController::handleEvent(float dts) {
	switch(event.type){
	case SDL_MOUSEBUTTONDOWN:
		if (event.button.button == SDL_BUTTON_RIGHT) {
			rotating = true;
			SDL_ShowCursor(SDL_DISABLE);
			SDL_WM_GrabInput(SDL_GRAB_ON);
		}
		break;
	case SDL_MOUSEBUTTONUP:
		if (event.button.button == SDL_BUTTON_LEFT) {
			Object *newbuilding = world->newObject(building->getPrototype());
			newbuilding->positionAt(buildPosition);
		}
		if (event.button.button == SDL_BUTTON_RIGHT) {
			rotating = false;
			motionController->setPitch(0);
			motionController->setYaw(0);
			SDL_ShowCursor(SDL_ENABLE);
			SDL_WM_GrabInput(SDL_GRAB_OFF);
		}
		break;
	case SDL_MOUSEMOTION:
		if (rotating) {
			motionController->setPitch(event.motion.yrel);
			motionController->setYaw(-event.motion.xrel);
		}

		// Update the buildPosition
		else {
			GLdouble winX = event.motion.x;
			GLdouble winY = event.motion.y;
			GLdouble winZ = 0.0;

		 	GLdouble objX = 0.0;
		 	GLdouble objY = 0.0;
		 	GLdouble objZ = 0.0;

		 	GLdouble modelview[16];
		 	GLdouble projection[16];

		 	GLint viewport[4];

			world->getCamera()->view();

			glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
		 	glGetDoublev(GL_PROJECTION_MATRIX, projection);
		 	glGetIntegerv(GL_VIEWPORT, viewport);
		 	gluUnProject(winX, viewport[3] - winY, winZ, modelview, projection, viewport, &objX, &objY, &objZ);

			Ray r;
			r.p = player->getPosition();
			Vector3 v = Vector3(objX, objY, objZ);
			r.d = v - r.p;

			Vector3 i;
			if (ground.intersection(r, true, i)) {
				buildPosition = Vector3(floor(i.x), 0, floor(i.z));
				building->positionAt(buildPosition);
			}
		}
		break;
	case SDL_KEYDOWN:
		if (event.key.keysym.sym == moveForward) {
			motionController->setMoveForward(true);
		}
		if (event.key.keysym.sym == moveBackward) {
			motionController->setMoveBackward(true);
		}
		if (event.key.keysym.sym == strafeLeft) {
			motionController->setStrafeLeft(true);
		}
		if (event.key.keysym.sym == strafeRight) {
			motionController->setStrafeRight(true);
		}
		break;
	case SDL_KEYUP:
		if (event.key.keysym.sym == moveForward) {
			motionController->setMoveForward(false);
		}
		if (event.key.keysym.sym == moveBackward) {
			motionController->setMoveBackward(false);
		}
		if (event.key.keysym.sym == strafeLeft) {
			motionController->setStrafeLeft(false);
		}
		if (event.key.keysym.sym == strafeRight) {
			motionController->setStrafeRight(false);
		}
		if (event.key.keysym.sym == SDLK_TAB) {
			buildingIndex = (buildingIndex + 1) % buildingMeshes.size();
			building->setPrototype(buildingMeshes[buildingIndex]);
		}
		break;
	}

}

MotionController* BuilderController::getMotionController() {
	return motionController;
}

BuilderController::~BuilderController() {
	delete motionController;
}
